//-------------------------------------------------------------------------------
//Vertex and pixel shader demonstrating ambient and diffuse lighting
// Ambient intensity values are pre baked
//------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------
// Global params provided by the app
//------------------------------------------------------------------------------------------------------
float4x4 g_mWorldViewProjection;
float flamability = 0.34000;
float pressure = 0.60000;
float powerBoost = 0.16000;
float intensity = 1.00000;
float speed = 0.15000;
float noisiness = 0.50000;
float time_0_X;
float explositivity = 0.44955;

texture g_NoiseTexture;
texture g_FlameTexture;

sampler3D NoiseTextureSampler =
sampler_state {
    Texture = <g_NoiseTexture>;
    MinFilter = Anisotropic;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
    AddressW = WRAP;
};

sampler FlameTextureSampler =
sampler_state {
    Texture = <g_FlameTexture>;
    MinFilter = Anisotropic;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU = CLAMP;
    AddressV = CLAMP;
};

//---------------------------------------------------------------------------------------------------------------------------
// Input channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct InputVS {
float3 Pos :
    POSITION;
float2 TextureUV:
    TEXCOORD;
};

//---------------------------------------------------------------------------------------------------------------------------
// Output channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct OutputVS {
float4 Pos :
    POSITION;
float2 TextureUV:
    TEXCOORD;
};

//---------------------------------------------------------------------------------------------------------------------------
// Vertex shader
//---------------------------------------------------------------------------------------------------------------------------
OutputVS ParticleShaderVS(InputVS input) {
    //Zero out our output
    OutputVS outVS = (OutputVS)0;

    //Transform to homogeneous clipspace
    outVS.Pos = mul(float4(input.Pos, 1.0f), g_mWorldViewProjection);
    outVS.TextureUV = input.TextureUV * 2;

    //return output
    return outVS;
}

//---------------------------------------------------------------------------------------------------------------------------
// Input channel pixel shader
//---------------------------------------------------------------------------------------------------------------------------
struct InputPS {
float2 TextureUV :
    TEXCOORD;
};

//---------------------------------------------------------------------------------------------------------------------------
// Pixel shader (input channel):output channel
//---------------------------------------------------------------------------------------------------------------------------
float4 ParticleShaderPS(InputPS input): COLOR {
    float t = frac(time_0_X * speed);

    // Alter the timing
    t = pow(t, explositivity);

    // The function f(t) = 6.75 * t * (t * (t - 2) + 1)
    // is a basic third degree pulse function with these properties:
    // f(0)  = 0
    // f(1)  = 0
    // f'(1) = 0
    // max(f(t)) = 1, where 0 < t < 1
    //
    // The basic idea of this function is a quick rise at the
    // beginning and then a slow smooth decline towards zero
    float size = intensity * 6.75 * t * (t * (t - 2) + 1);

    float dist = length(input.TextureUV) / (0.1 + size);

    // Higher flamability => quicker move away from center
    // Higher pressure => tighter packing
    float4 n = tex3D(NoiseTextureSampler, float3(noisiness * input.TextureUV, flamability * time_0_X - pressure * dist));

    float4 flame = tex1D(FlameTextureSampler, size * powerBoost + size * (2 * n.r - dist));
    flame.a = n.a;

    return flame;
}

technique Particle_Shader {
    pass P0
    {
        Lighting = TRUE;
        SpecularEnable = TRUE;
        FillMode = Solid;
        vertexShader = compile vs_3_0 ParticleShaderVS();
        pixelShader = compile ps_3_0 ParticleShaderPS();
    }
}

technique Particle_Shader_Normal_Alpha {
    pass P0
    {
        Lighting = TRUE;
        SpecularEnable = TRUE;
        FillMode = Solid;
        ZEnable = true;
        ZWriteEnable = true;
        ZFunc = LessEqual;
        AlphaBlendEnable = true;
        SrcBlend = SrcAlpha;
        DestBlend = InvSrcAlpha;
        BlendOp = Add;
        vertexShader = compile vs_3_0 ParticleShaderVS();
        pixelShader = compile ps_3_0 ParticleShaderPS();
    }
}